/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 * Description: debug process
 * Author: -
 * Create: 2021.7.23
 */

#include <stdlib.h>
#include <stdarg.h>
#include <execinfo.h>

#include "securec.h"

#include "udk_common.h"
#include "udk_log.h"

#define LINE_LEN 128
#define HEX_UNIT_LEN 16
void udk_hexdump(FILE *f, const char *title, const void *buf, uint32_t len)
{
    uint32_t i, ofst;
    int out;
    const char *data = buf;
    char line[LINE_LEN];

    (void)fprintf(f, "%s at [0x%lx], len=%u\n", title ? title: " Dump data", udk_get_ptr(data), len);

    ofst = 0;
    while (ofst < len) {
        out = snprintf_s(line, LINE_LEN, LINE_LEN, "%08X:", ofst);
        for (i = 0; i < HEX_UNIT_LEN; ++i) {
            if (ofst + i < len) {
                (void)snprintf_s(line + out, LINE_LEN - out, LINE_LEN - out, " %02X", (*(data + ofst + i) & 0xff));
            } else {
                (void)strcpy_s(line + out, LINE_LEN - out, "   ");
            }
            out += 0x3;
        }

        for (; i <= HEX_UNIT_LEN; ++i) {
            out += snprintf_s(line + out, LINE_LEN - out, LINE_LEN - out, " | ");
        }

        for (i = 0; ofst < len && i < HEX_UNIT_LEN; ++i, ++ofst) {
            char c = data[ofst];
            
            if (c < ' ' || c > '~') {
                c = '.';
            }
            out += snprintf_s(line + out, LINE_LEN - out, LINE_LEN - out, "%c", c);
        }
        (void)fprintf(f, "%s\n", line);
    }
    (void)fflush(f);
}

#define BACKTRACE_SIZE 256
void udk_dump_stack(void)
{
    void *function[BACKTRACE_SIZE];
    char **symbol = NULL;
    int size;

    size = backtrace(function, BACKTRACE_SIZE);
    symbol = backtrace_symbols(function, size);
    if (symbol == NULL) {
        return;
    }

    while (size > 0) {
        UDK_LOG(ERR, COMMON, "%d: [%s]\n", size, symbol[size - 1]);
        size--;
    }

    free(symbol);
}

void udk_panic_handle(const char *func_name, const char *format, ...)
{
    va_list ap;

    UDK_LOG(CRIT, COMMON, "PANIC in %s():\n", func_name);

    va_start(ap, format);
    udk_vlog(__func__, __LINE__, UDK_LOG_CRIT, UDK_LOGTYPE_COMMON, format, ap);
    va_end(ap);

    udk_dump_stack();
    abort();
}
